package cn.lg.soar.common.util.data;

import cn.lg.soar.common.data.tree.ITreeResult;
import cn.lg.soar.common.data.tree.ITreeSource;
import cn.lg.soar.common.data.tree.ITreeData;

import java.util.*;
import java.util.function.*;

/**
 * @author luguoxiang
 * @date 2022/8/20
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface TreeUtil {

    /**
     * 将list数据转为树形数据（用于源数据和结果数据不同类型的情况）
     * @param list 扁平数据
     * @param parentId 父id
     * @param handler 转换函数
     * @param <ID> id类型
     * @param <T> 源数据类型
     * @param <R> 树形数据类型
     * @return
     */
    static <ID, T extends ITreeSource<ID>, R extends ITreeResult<R>> List<R> toTree(List<T> list, ID parentId, Function<T, R> handler) {
        return ITreeResult.valueOf(list, parentId, handler);
    }

    /**
     * 将list数据转为树形数据（用于源数据和结果数据相同类型的情况）
     * @param list 扁平数据
     * @param parentId 根数据父id
     * @param <ID>
     * @param <T>
     * @return
     */
    static <ID, T extends ITreeData<ID, T>> List<T> toTree(List<T> list, ID parentId) {
        return ITreeData.toTree(list, parentId);
    }

    /**
     * 树形数据扁平化（用于源数据和结果数据不同类型的情况）
     * @param tree 树数据
     * @param handler 转换函数
     * @param <ID> id类型
     * @param <T> 源数据类型
     * @param <R> 树形数据类型
     * @return
     */
    static <ID, R extends ITreeResult<R>, S extends ITreeSource<ID>> List<S> toList(List<R> tree, Function<R, S> handler) {
        return ITreeSource.valueOf(tree, handler);
    }

    /**
     * 树形数据扁平化（用于源数据和结果数据相同类型的情况）
     * @param tree 树数据
     * @param <ID>
     * @param <T>
     * @return
     */
    static <ID, T extends ITreeData<ID, T>> List<T> toList(List<T> tree) {
        return ITreeData.toList(tree);
    }

    /**
     * 遍历
     * @param tree 树形数据
     * @param consumer 消费函数
     * @param parent 父数据
     * @param <T>
     */
    static <T extends ITreeResult<T>>void forEach(Collection<T> tree, BiConsumer<T, T> consumer, T parent) {
        ITreeResult.forEach(tree, consumer, parent);
    }

    /**
     * 遍历
     * @param tree 树形数据
     * @param consumer 消费函数
     * @param <T>
     */
    static <T extends ITreeResult<T>>void forEach(Collection<T> tree, Consumer<T> consumer) {
        ITreeResult.forEach(tree, consumer);
    }

    /**
     * 转换
     * @param tree 树形数据
     * @param converter 转换函数
     * @param parent 父数据
     * @param <T>
     * @param <R>
     * @return
     */
    static <T extends ITreeResult<T>, R extends ITreeResult<R>> List<R> map(Collection<T> tree, BiFunction<T, T, R> converter, T parent) {
        return ITreeResult.map(tree, converter, parent);
    }

    /**
     * 转换
     * @param tree 树形数据
     * @param converter 转换函数
     * @param <T>
     * @param <R>
     * @return
     */
    static <T extends ITreeResult<T>, R extends ITreeResult<R>> List<R> map(Collection<T> tree, Function<T, R> converter) {
        return ITreeResult.map(tree, converter);
    }

    /**
     * 筛选
     * @param tree 树形数据
     * @param predicate 条件函数
     * @param parent 父数据
     * @param <T>
     * @return
     */
    static <T extends ITreeResult<T>>List<T> filter(Collection<T> tree, BiPredicate<T, T> predicate, T parent) {
        return ITreeResult.filter(tree, predicate, parent);
    }

    /**
     * 筛选
     * @param tree 树形数据
     * @param predicate 条件函数
     * @param <T>
     * @return
     */
    static <T extends ITreeResult<T>>List<T> filter(Collection<T> tree, Predicate<T> predicate) {
        return ITreeResult.filter(tree, predicate);
    }

    /**
     * 查找
     * @param tree 树形数据
     * @param predicate 条件函数
     * @param parent 父数据
     * @param <T>
     * @return
     */
    static <T extends ITreeResult<T>>T find(Collection<T> tree, BiPredicate<T, T> predicate, T parent) {
        return ITreeResult.find(tree, predicate, parent);
    }

    /**
     * 查找
     * @param tree 树形数据
     * @param predicate 条件函数
     * @param <T>
     * @return
     */
    static <T extends ITreeResult<T>>T find(Collection<T> tree, Predicate<T> predicate) {
        return ITreeResult.find(tree, predicate);
    }

    /**
     * 查找元素链（从根节点到目标元素的路径，记得倒转）
     * @param tree 树形数据
     * @param predicate 条件函数
     * @param parent 父数据
     * @return
     * @param <T>
     */
    static <T extends ITreeResult<T>>List<T> findLinkR(Collection<T> tree, BiPredicate<T, T> predicate, T parent) {
        return ITreeResult.findLinkR(tree, predicate, parent);
    }

    /**
     * 查找元素链（从根节点到目标元素的路径，记得倒转）
     * @param tree 树形数据
     * @param predicate 条件函数
     * @return
     * @param <T>
     */
    static <T extends ITreeResult<T>>List<T> findLinkR(Collection<T> tree, Predicate<T> predicate) {
        return ITreeResult.findLinkR(tree, predicate);
    }

    /**
     * 查找元素链（从根节点到目标元素的路径）
     * @param tree 树形数据
     * @param predicate 条件函数
     * @param parent 父数据
     * @return
     * @param <T>
     */
    static <T extends ITreeResult<T>>List<T> findLink(Collection<T> tree, BiPredicate<T, T> predicate, T parent) {
        return ITreeResult.findLink(tree, predicate, parent);
    }

    /**
     * 查找元素链（从根节点到目标元素的路径）
     * @param tree 树形数据
     * @param predicate 条件函数
     * @return
     * @param <T>
     */
    static <T extends ITreeResult<T>>List<T> findLink(Collection<T> tree, Predicate<T> predicate) {
        return ITreeResult.findLink(tree, predicate);
    }

    /**
     * 搜索（符合条件的数据返回数据和数据上下级）
     * @param tree 数据
     * @param predicate 条件函数
     * @param parent 父数据
     * @return
     * @param <V>
     * @param <T>
     * @param <R>
     */
    static <T extends ITreeResult<T>>List<T> query(Collection<T> tree, BiPredicate<T, T> predicate, T parent) {
        return ITreeResult.query(tree, predicate, parent);
    }

    /**
     * 搜索（符合条件的数据返回数据和数据上下级）
     * @param tree 数据
     * @param predicate 条件函数
     * @return
     * @param <V>
     * @param <T>
     * @param <R>
     */
    static <T extends ITreeResult<T>>List<T> query(Collection<T> tree, Predicate<T> predicate) {
        return ITreeResult.query(tree, predicate);
    }

    /**
     * 排序
     * @param tree 树形数据
     * @param comparator 排序比较函数
     * @param <T>
     * @return
     */
    static <T extends ITreeResult<T>>void sort(List<T> tree, Comparator<? super T> comparator) {
        ITreeResult.sort(tree, comparator);
    }

}
